package com.app.micaihu.view.camera.activity;

import android.graphics.Typeface;
import android.hardware.Camera;
import android.opengl.Matrix;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.app.base.BaseActivity;
import com.app.micaihu.R;
import com.app.micaihu.base.BaseOldActivity;
import com.app.micaihu.configure.Config;
import com.app.micaihu.view.camera.view.LongClickImageView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

import jp.co.cyberagent.android.gpuimage.GPUImageFilter;
import jp.co.cyberagent.android.gpuimage.GPUImageFilterGroup;
import jp.co.cyberagent.android.gpuimage.GPUImageTransformFilter;
import jp.co.cyberagent.android.gpuimage.GPUImageView;
import jp.co.cyberagent.android.gpuimage.util.CameraHelper;

public class CameraActivity extends BaseActivity implements View.OnClickListener {

    private float currentScale = 1.0F;
    private float currentZoom = 1.0F;
    private FrameLayout flGpu;
    private ImageView ivBack;
    private LongClickImageView ivZoomUp, ivZoomDown;
    private TextView tvZoomNum, tvZoomNumX;
    private GPUImageView mGPUImage;
    private CameraHelper mCameraHelper;
    private CameraLoader mCameraLoader;
    private GPUImageTransformFilter transformFilter;
    private GPUImageFilterGroup gpuImageFilterGroup;
    private int orientation;


    @Override
    protected void initBar(boolean initBar) {
        super.initBar(false);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCameraLoader != null) {
            mCameraLoader.onPause();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mGPUImage != null) {
            mGPUImage.onPause();
            flGpu.removeView(this.mGPUImage);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        initCamera();
        mCameraLoader.onResume();
        if (mGPUImage != null) {
            mGPUImage.onResume();
        }
        if (mCameraLoader.getmCameraInstance() != null && mGPUImage != null) {
            zoomTo(currentZoom);
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mGPUImage != null) {
            mGPUImage.onPause();
            flGpu.removeView(this.mGPUImage);
        }
        if (mCameraLoader != null) {
            mCameraLoader.onPause();
        }
    }

    private void setViewData() {
        flGpu = findViewById(R.id.flGpu);
        ivZoomUp = findViewById(R.id.ivZoomUp);
        ivZoomDown = findViewById(R.id.ivZoomDown);
        tvZoomNum = findViewById(R.id.tvZoomNum);
        tvZoomNumX = findViewById(R.id.tvZoomNumX);
        ivBack = findViewById(R.id.ivBack);
        ivZoomUp.setIntervalTime(80);
        ivZoomDown.setIntervalTime(80);

        Typeface customFont = Typeface.createFromAsset(this.getAssets(), Config.AssetsPath.digital);
        tvZoomNum.setTypeface(customFont);
        tvZoomNumX.setTypeface(customFont);

    }

    private void initCamera() {
        mCameraHelper = new CameraHelper(this);
        mCameraLoader = new CameraLoader();
        mGPUImage = new GPUImageView(this);
        flGpu.addView(mGPUImage);
        transformFilter = new GPUImageTransformFilter();
        List<GPUImageFilter> filters = new LinkedList<>();
        filters.add(transformFilter);
        gpuImageFilterGroup = new GPUImageFilterGroup(filters);
        mGPUImage.setFilter(gpuImageFilterGroup);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.camera_activity;
    }

    @Override
    protected void setData() {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setViewData();
    }

    private class CameraLoader {

        private int mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
        private Camera mCameraInstance;

        public void onResume() {
            setUpCamera(mCurrentCameraId);
        }

        public void onPause() {
            releaseCamera();
        }

        public void switchCamera() {
            releaseCamera();
            mCurrentCameraId = (mCurrentCameraId + 1) % mCameraHelper.getNumberOfCameras();
            setUpCamera(mCurrentCameraId);
        }

        public Camera getmCameraInstance() {
            return mCameraInstance;
        }

        public int getCameraId() {
            return mCurrentCameraId;
        }

        private void setUpCamera(final int id) {
            mCameraInstance = getCameraInstance(id);
            if (mCameraInstance == null) return;
            Camera.Parameters parameters = mCameraInstance.getParameters();
            if (parameters == null) return;
            if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }
            mCameraInstance.setParameters(parameters);
            orientation = mCameraHelper.getCameraDisplayOrientation(CameraActivity.this, mCurrentCameraId);
            CameraHelper.CameraInfo2 cameraInfo = new CameraHelper.CameraInfo2();
            mCameraHelper.getCameraInfo(mCurrentCameraId, cameraInfo);
            boolean flipHorizontal = cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT;
            if (mGPUImage.getGPUImage() != null) {
                mGPUImage.getGPUImage().setUpCamera(mCameraInstance, orientation, flipHorizontal, false);
            }
        }

        /**
         * A safe way to get an instance of the Camera object.
         */
        private Camera getCameraInstance(final int id) {
            Camera c = null;
            try {
                c = mCameraHelper.openCamera(id);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return c;
        }

        private void releaseCamera() {
            if (mCameraInstance != null) {
                try {
                    mCameraInstance.setPreviewCallback(null);
                    mCameraInstance.stopPreview();
                    mCameraInstance.release();
                    mCameraInstance = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void addListeners() {
        ivZoomUp.setOnClickListener(this);
        ivZoomDown.setOnClickListener(this);
        ivBack.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        float zoomNumTimes = 0.5f;
        switch (v.getId()) {
            case R.id.ivBack:
                finish();
                break;
            case R.id.ivZoomUp:
                HashMap<String, Object> map = new HashMap<>();
                map.put("focus_big", "放大");
//                MobclickAgentUtils.event(Config.EventId.focus_button, map);
                zoomTo(this.currentZoom + zoomNumTimes);
                break;
            case R.id.ivZoomDown:
                HashMap<String, Object> map1 = new HashMap<>();
                map1.put("focus_small", "缩小");
//                MobclickAgentUtils.event(Config.EventId.focus_button, map1);
                zoomTo(this.currentZoom - zoomNumTimes);
                break;
        }
    }


    /**
     * 获取实际意义的最大放大倍数，如4.0，10.0
     * 未完成
     *
     * @return
     */
    public float getPictureMaxZoom() {
        if (mCameraLoader == null) return 1.0f;
        Camera camera = mCameraLoader.getmCameraInstance();
        if (camera == null) return 1.0f;
        Camera.Parameters localParameters = camera.getParameters();
        if (localParameters == null) return 1.0f;
        List<Integer> allZoomRatio = localParameters.getZoomRatios();
        if (null == allZoomRatio) {
            return 1.0f;
        } else {
            return Math.round(allZoomRatio.get(allZoomRatio.size() - 1) / 100f);
        }
    }

    private void updateZoom() {
        try {
            Camera.Parameters localParameters = mCameraLoader.getmCameraInstance().getParameters();
//            LogUtils.e("tag", "maxZoom->" + maxZoom);
            if (localParameters.isZoomSupported()) {
                List<Integer> zoomRatios = localParameters.getZoomRatios();
                if (zoomRatios != null) {
                    if (zoomRatios.size() != 0) {
                    }
                } else {
                    zoomRatios = new ArrayList<>();
                    zoomRatios.add(100);
                }
                int i = getCurrentZoomIndex(zoomRatios);

                if (localParameters.getZoom() != i) {
                    localParameters.setZoom(i);
                    mCameraLoader.getmCameraInstance().setParameters(localParameters);
                }
                if (i < zoomRatios.size() - 1) {
                    this.currentScale = 1.0F;
                } else {
                    float v = ((Integer) zoomRatios.get(i)).intValue() / 100.0F;
                    this.currentScale = (this.currentZoom / v);
                }
            }
        } catch (Exception localException) {
            localException.printStackTrace();
        }

        float[] arrayOfFloat = new float[16];
        Matrix.setIdentityM(arrayOfFloat, 0);
        Matrix.scaleM(arrayOfFloat, 0, this.currentScale, this.currentScale, this.currentScale);
        if (transformFilter != null) {
            transformFilter.setTransform3D(arrayOfFloat);
        }
        if (currentZoom <= 1.0f) {
            tvZoomNum.setText(String.format(Locale.US, "%.1f", this.currentZoom));
        } else {
            tvZoomNum.setText(String.format(Locale.US, "%.1f", this.currentZoom * 1.5));
        }

    }

    private int getCurrentZoomIndex(List<Integer> paramList) {
        int j;
        for (int i = 0; i < paramList.size() - 1; i = j) {
            double d1 = ((Integer) paramList.get(i)).intValue();
            Double.isNaN(d1);
            d1 /= 100.0D;
            j = i + 1;
            double d2 = ((Integer) paramList.get(j)).intValue();
            Double.isNaN(d2);
            d2 /= 100.0D;
            float f = this.currentZoom;
            if ((d1 <= f) && (f <= d2)) {
                return i;
            }
        }
        return paramList.size() - 1;
    }


    public void zoomTo(float paramFloat) {
        this.currentZoom = paramFloat;
        paramFloat = this.currentZoom;
        if (paramFloat > 50.0F) {
            this.currentZoom = 50.0F;
        } else if (paramFloat < 1.0F) {
            this.currentZoom = 1.0F;
        }
        this.currentScale = this.currentZoom;
        updateZoom();
    }

}
